// service/qiniu.js
import {BaseService} from 'egg-cool-service';

const fs = require ("fs");
const path = require ("path");
const qiniu = require ("qiniu");
const awaitWriteStream = require ("await-stream-ready").write;
const sendToWormhole = require ("stream-wormhole");
// const md5 = require("md5");

//需要填写你的 Access Key 和 Secret Key , bucket空间
const accessKey = '';
const secretKey = '';
const mac = new qiniu.auth.digest.Mac (accessKey , secretKey);
const imageUrl = ""; // 空间绑定的域名
const bucket = '';
let config = new qiniu.conf.Config ();
config.zone = qiniu.zone.Zone_z0;

// const options = {
//    scope: bucket,
//    expires: 315360000000,//十年
//    returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}',
//    force: true,
//    callbackBodyType: 'application/json'
// };

/**
 * 文件
 */
export default class Qiniu extends BaseService {

    getUploadDirName () {
        const date = new Date ();
        let month : number|string = Number.parseInt (String (date.getMonth ())) + 1;
        month = month.toString ().length > 1 ? month : `0${ month }`;
        const dir = `${ date.getFullYear () }${ month }${ date.getDate () }`;
        return dir;
    }

    async upload (opt = {
        initStream : '' ,
        filename : '' ,
        initDirName : ''
    }) {
        const {ctx} = this;
        const {initStream , initDirName} = opt;
        // const extraParams = await this.parse(ctx.req);
        // @ts-ignore
        //   const {init} = extraParams && extraParams.fields;
        //   const [files, fields] = await this.multipart();
        let stream;
        let timeDirName = this.getUploadDirName ();
        let dirName = '/';
        if ( !initStream ) {
            stream = await ctx.getFileStream ();
            dirName = stream.fields && stream.fields.dirName ? stream.fields.dirName : '新建文件夹';
        } else {
            stream = initStream;
            dirName = initDirName;
        }
        const filename =
                new Date ().getTime () + encodeURIComponent (stream.filename ? stream.filename : opt.filename);
        // const filename =
        //         md5(stream.filename?stream.filename:opt.filename) + path.extname(stream.filename?stream.filename:opt.filename).toLocaleLowerCase();
        // 最终要保存到的文件夹目录
        // const dirName = this.getUploadDirName();
        const dir1 = path.resolve (__dirname , `../../public/uploads/${ timeDirName }`);
        if ( !fs.existsSync (dir1) ) {
            fs.mkdirSync (dir1);
        }
        const dir2 = path.resolve (__dirname , `../../public/uploads/${ timeDirName }/${ dirName }`);
        if ( !fs.existsSync (dir2) ) {
            fs.mkdirSync (dir2);
        }
        const localFilePath = path.resolve (__dirname , `../../public/uploads/${ timeDirName }/${ dirName }` , filename);
        // if(!initStream){
        //     //file模式
        //     console.log('file模式')
        //
        // }
        //流的模式
        const writeStream = fs.createWriteStream (localFilePath);
        try {
            await awaitWriteStream (stream.pipe (writeStream));
            try {
                return await this.qiNiuMethod (opt , filename , localFilePath , dirName , timeDirName);
            } catch (e) {
                throw new Error ('七牛上传错误：' + e);
            }
        } catch (err) {
            //如果出现错误，关闭管道
            await sendToWormhole (stream);
            // return false;
            throw new Error ('上传文件失败：' + err);
        }

    }

    async qiNiuMethod (opt , filename , localFilePath , dirName , timeDirName) {
        const formUploader = new qiniu.form_up.FormUploader (config);
        const putExtra = new qiniu.form_up.PutExtra ();
        // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
        // putPolicy.Scope = bucket + ":" + saveKey;
        let options = {
            // 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖)，请使用 SCOPE = "BUCKET:KEY"
            scope : bucket ,
            expires : 315360000000 ,//十年
            callbackBodyType : 'application/json' ,
            // returnBody : '{"key":"$(key)","name": $(fname),"size": $(fsize),"imageInfo": $(imageInfo),"hash": $(etag),"mimeType":$(mimeType)}'
            returnBody : '{"key":"$(key)","name": $(fname),"size": $(fsize),"imageInfo": $(imageInfo),"hash": $(etag),"mimeType":$(mimeType),"avinfo":$(avinfo)}'
        };
        if ( opt.initStream ) {
            // options.scope = bucket + ":" + filename
        }
        const putPolicy = new qiniu.rs.PutPolicy (options);
        const uploadToken = putPolicy.uploadToken (mac);
        const imgSrc = await new Promise ((resolve , reject) => {
            formUploader.putFile (
                    uploadToken ,
                    null ,
                    localFilePath ,
                    putExtra ,
                    (respErr , respBody , respInfo) => {
                        if ( respErr ) {
                            reject (respErr);
                            return;
                        }
                        if ( respInfo.statusCode == 200 ) {
                            // 公开空间访问链接
                            const {key} = respBody;
                            const bucketManager = new qiniu.rs.BucketManager (mac , options);
                            const publicBucketDomain = imageUrl;
                            var publicDownloadUrl = bucketManager.publicDownloadUrl (publicBucketDomain , key);
                            // if(shuiyin){
                            //     resolve(`${publicDownloadUrl}-qianyouzhuo`)
                            // }else {
                            //     resolve(`${publicDownloadUrl}-logo`)
                            // }
                            respBody.url = `${ publicDownloadUrl }`;
                            respBody.staticFilePath = `/uploads/${ timeDirName }/${ dirName }/${ filename }`;

                            if ( ['video/mp4' , 'video/ogg' , 'video/flv' , 'video/avi' , 'video/wmv' , 'video/rmvb' , 'video/mov'].indexOf (respBody.mimeType) > - 1 ) {
                                delete respBody.imageInfo;
                            } else {
                                delete respBody.avinfo;
                            }
                            resolve (respBody);
                            // 上传之后删除本地文件
                            fs.unlinkSync (localFilePath);
                        } else {
                            console.log ('respInfo' , respInfo);
                            console.log ('filename' , filename);
                            reject (JSON.stringify (respInfo));
                            if ( fs.existsSync (localFilePath) ) {
                                fs.unlinkSync (localFilePath);
                            }
                        }
                    }
            );
        });
        if ( imgSrc !== "" ) {
            return {
                url : imgSrc
            };
        } else {
            return {
                url : ''
            };
        }
    }

}
